package com.donger.iot.core.south.gateway.manager;

import com.donger.iot.core.south.gateway.access.DeviceAccessor;
import com.donger.iot.core.center.device.Device;
import lombok.Data;

import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Data
public abstract class SimpleDeviceAccessorManager implements DeviceAccessorManager {
    /**
     * DeviceAccessor运行的线程池
     */
    private DeviceAccessorPoolExecutor deviceAccessorPoolExecutor;
    /**
     * 保活线程池，保证每个设备对应的DeviceAccessor存活，断开重连
     */
    private ThreadPoolExecutor keepAlivedPoolExecutor;
    /**
     * 设备列表
     */
    private List<Device> deviceList;
    /**
     * 是否开始检查
     */
    private boolean isCheck;
    /**
     * 是否开始检查
     */
    private boolean isRunning;

    /**
     * 检查频率，单位：毫秒 millisecond
     * 默认5s
     */
    private long checkRate = 5000L;

    public SimpleDeviceAccessorManager() {
        deviceAccessorPoolExecutor = new DeviceAccessorPoolExecutor(2, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>());

    }

    @Override
    public void stop() {
        if (isCheck) {
            stopCheck();
        }
        this.disConnect();

    }

    @Override
    public void startCheck() {
        isCheck = true;
        this.keepAlivedPoolExecutor.execute(() -> {
            while (isCheck) {
                try {
                    Thread.sleep(checkRate);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //完成线程检查，保活等相关逻辑
                deviceList.forEach(device -> {
                    boolean exist = false;
                    for (DeviceAccessor deviceAccessor : deviceAccessorPoolExecutor.getAliveThreadList()) {
                        if (deviceAccessor.getDevice().equals(device)) {
                            exist = true;
                        }
                    }
                    if (!exist) {
                        //如果不存在，也就是线程退出了，重新启动一个线程
                        deviceAccessorPoolExecutor.execute(getDeviceAccessorByDevice(device));
                    }
                });

            }
        });
    }

    public abstract DeviceAccessor getDeviceAccessorByDevice(Device device);

    @Override
    public void stopCheck() {
        isCheck = false;

    }

    @Override
    public void connect() {
        this.deviceList.forEach(device -> this.deviceAccessorPoolExecutor.execute(this.getDeviceAccessorByDevice(device)));
        this.isRunning = true;
    }

    @Override
    public void disConnect() {
        this.deviceAccessorPoolExecutor.shutdown();
        this.isRunning = false;
    }

    @Override
    public boolean isRunning() {
        return this.isRunning;
    }

    @Override
    public boolean isChecking() {
        return this.isCheck;
    }


}
